#pragma once 

#include <iostream>
#include <queue>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>

#define NUM 5

template<typename T>
class RingQueue{
  private:
    int capacity;
    std::vector<T> ring_queue;
    int task_num;
    int space_num;
    sem_t blank_sem;
    sem_t data_sem;

  public:
    RingQueue(int _capacity = NUM):capacity(_capacity), task_num(0), space_num(0)
    {
      //生产者的初始信号量value为0
      sem_init(&blank_sem, 0, capacity);
      //消费者的初始信号量value为capacity
      sem_init(&data_sem, 0, 0);
      ring_queue.resize(capacity);
    }

    void Push(const T& in)
    {
      P(blank_sem);
      ring_queue[task_num++] = in;
      task_num %= capacity;
      V(data_sem);
    }

    void Pop(T& out)
    {
      P(data_sem);
      out = ring_queue[space_num++];
      space_num %= capacity;
      V(blank_sem);
    }
    
    void P(sem_t& sem)
    {
      sem_wait(&sem);
    }
    
    void V(sem_t& sem)
    {
      sem_post(&sem);
    }

    bool IsEmpty()const
    {
      return space_num == task_num ? true : false;
    }
    
    bool IsFull()const
    {
      return abs(space_num - task_num) + 1 == capacity;
    }

    ~RingQueue()
    {
      sem_destroy(&blank_sem);
      sem_destroy(&data_sem);
    }
};
